package com.ruoyi.common.utils.ftp;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

public class FtpUtil {
    private static final Logger logger = LoggerFactory.getLogger(FtpUtil.class);

    private String server;
    private int port;
    private String user;
    private String password;

    public FtpUtil(String server, int port, String user, String password) {
        this.server = server;
        this.port = port;
        this.user = user;
        this.password = password;
    }

    /**
     * 连接 FTP 服务器
     *
     * @return FTPClient 对象
     */
    public FTPClient connect() {
        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient.connect(server, port);
            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                logger.error("FTP 服务器拒绝连接，响应码: {}", reply);
                return null;
            }
            if (!ftpClient.login(user, password)) {
                ftpClient.logout();
                logger.error("FTP 登录失败，用户名或密码错误");
                return null;
            }
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
            logger.info("成功连接到 FTP 服务器");
        } catch (IOException e) {
            logger.error("连接 FTP 服务器时发生 I/O 错误", e);
            return null;
        }
        return ftpClient;
    }

    /**
     * 上传文件到 FTP 服务器
     *
     * @param localFilePath  本地文件路径
     * @param remoteFilePath 远程文件路径
     * @return 上传是否成功
     */
    public boolean uploadFile(String localFilePath, String remoteFilePath) {
        FTPClient ftpClient = connect();
        if (ftpClient == null) {
            return false;
        }
        try (InputStream inputStream = new FileInputStream(new File(localFilePath))) {
            boolean result = ftpClient.storeFile(remoteFilePath, inputStream);
            if (result) {
                logger.info("文件上传成功: {}", remoteFilePath);
            } else {
                logger.error("文件上传失败: {}", remoteFilePath);
            }
            return result;
        } catch (IOException e) {
            logger.error("上传文件时发生 I/O 错误", e);
            return false;
        } finally {
            disconnect(ftpClient);
        }
    }

    /**
     * 从 FTP 服务器下载文件
     *
     * @param remoteFilePath 远程文件路径
     * @param localFilePath  本地文件路径
     * @return 下载是否成功
     */
    public boolean downloadFile(String remoteFilePath, String localFilePath) {
        FTPClient ftpClient = connect();
        if (ftpClient == null) {
            return false;
        }
        try (OutputStream outputStream = new FileOutputStream(new File(localFilePath))) {
            boolean result = ftpClient.retrieveFile(remoteFilePath, outputStream);
            if (result) {
                logger.info("文件下载成功: {}", localFilePath);
            } else {
                logger.error("文件下载失败: {}", localFilePath);
            }
            return result;
        } catch (IOException e) {
            logger.error("下载文件时发生 I/O 错误", e);
            return false;
        } finally {
            disconnect(ftpClient);
        }
    }

    /**
     * 删除 FTP 服务器上的文件
     *
     * @param remoteFilePath 远程文件路径
     * @return 删除是否成功
     */
    public boolean deleteFile(String remoteFilePath) {
        FTPClient ftpClient = connect();
        if (ftpClient == null) {
            return false;
        }
        try {
            boolean result = ftpClient.deleteFile(remoteFilePath);
            if (result) {
                logger.info("文件删除成功: {}", remoteFilePath);
            } else {
                logger.error("文件删除失败: {}", remoteFilePath);
            }
            return result;
        } catch (IOException e) {
            logger.error("删除文件时发生 I/O 错误", e);
            return false;
        } finally {
            disconnect(ftpClient);
        }
    }

    /**
     * 断开与 FTP 服务器的连接
     *
     * @param ftpClient FTPClient 对象
     */
    public void disconnect(FTPClient ftpClient) {
        if (ftpClient.isConnected()) {
            try {
                ftpClient.logout();
                ftpClient.disconnect();
                logger.info("已断开与 FTP 服务器的连接");
            } catch (IOException e) {
                logger.error("断开 FTP 连接时发生 I/O 错误", e);
            }
        }
    }

    /**
     * 列出指定目录下的文件和文件夹
     *
     * @param remoteDirectory 远程目录路径
     * @return FTPFile 数组
     */
    public FTPFile[] listFiles(String remoteDirectory) {
        FTPClient ftpClient = connect();
        if (ftpClient == null) {
            return new FTPFile[0];
        }
        try {
            return ftpClient.listFiles(remoteDirectory);
        } catch (IOException e) {
            logger.error("列出文件时发生 I/O 错误", e);
            return new FTPFile[0];
        } finally {
            disconnect(ftpClient);
        }
    }

    public boolean renameFile(String remoteFilePath, String newFilePath) {
        FTPClient ftpClient = connect();
        if (ftpClient == null) {
            return false;
        }
        try {
            boolean result = ftpClient.rename(remoteFilePath, newFilePath);
            if (result) {
                logger.info("文件名称修改成功: form {}, to {}", remoteFilePath, newFilePath);
            } else {
                logger.error("文件名称修改失败: form {}, to {}", remoteFilePath, newFilePath);
            }
            return result;
        } catch (IOException e) {
            logger.error("删除文件时发生 I/O 错误", e);
            return false;
        } finally {
            disconnect(ftpClient);
        }
    }
}